package org.example.controller;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.example.TestApplication;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.util.LinkedMultiValueMap;

import java.util.Date;

/**
 * @program: example-web-framework-extends-2x
 * @description:
 * @author: Chenjiabin
 * @create: 2018-05-14 18:54
 **/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {TestApplication.class})
@AutoConfigureMockMvc
@WithMockUser(username = "root", roles = {"root", "超级管理员"})
//@Transactional
public class RequestResponseBodyControllerTester {
    @Autowired
    private ServerProperties properties;
    @Autowired
    private MockMvc mvc;

    @Test
    public void requestBody() throws Exception {
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/request_response_body/request_body");
        builder.content("{'id':'id','birthDay':'2019-04-23','name':'name','orders':[{'id':'id','name':'name'}],'password':'password','username':'username'}");
        builder.contentType("application/json");
        ResultActions resultActions = this.mvc.perform(builder);

        resultActions.andExpect(MockMvcResultMatchers.status().isOk());
        resultActions.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8));
        //打印信息
        resultActions.andDo(MockMvcResultHandlers.print());

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.id", Matchers.equalTo("id")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.username", Matchers.equalTo("username")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.status").doesNotExist());
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.birthDay", Matchers.equalTo("2019-04-23")));

    }

    @Test
    public void filter() throws Exception {
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/request_response_body/filter");
        builder.header("Accept", "application/json");
        builder.header("json.excludeProperties", "status.error");
        builder.header("json.dateFormat", "yyyy-MM-dd");

        ResultActions resultActions = this.mvc.perform(builder);

        resultActions.andExpect(MockMvcResultMatchers.status().isOk());
        resultActions.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8));
        //打印信息
        resultActions.andDo(MockMvcResultHandlers.print());
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.id").doesNotExist());
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.username", Matchers.equalTo("username")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.status.error").doesNotExist());

        //此预测是服务端决定的格式（ @JSON(format = "yyyy-MM-dd")）
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.birthDay", Matchers.equalTo(DateFormatUtils.format(new Date(), "yyyy-MM-dd"))));

        //此预测是客户端决定的格式（builder.header("json.dateFormat", "yyyy-MM-dd")）
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.cdt", Matchers.equalTo(DateFormatUtils.format(new Date(), "yyyy-MM-dd"))));
    }


    @Test
    public void resolveEntityArgumentTester() throws Exception {
        LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        params.add("user.id", "uid0");
        params.add("user.username", "username0");
        params.add("user.name", "name0");
        params.add("user.birthDay", "2019-09-09");
        params.add("user.orders[0].id", "oid0");
        params.add("user.orders[0].name", "order0");
        params.add("test", "test");
        params.add("user1.id", "uid1");

        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/request_response_body/resolve_entity_argument");
        builder.contentType("application/x-www-form-urlencoded ");
        builder.params(params);

        ResultActions resultActions = this.mvc.perform(builder);

        resultActions.andExpect(MockMvcResultMatchers.status().isOk());
        resultActions.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8));
        //打印信息
        resultActions.andDo(MockMvcResultHandlers.print());
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.test", Matchers.equalTo("test")));

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.id", Matchers.equalTo("uid0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.name", Matchers.equalTo("name0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.username", Matchers.equalTo("username0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.birthDay", Matchers.equalTo("2019-09-09")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.orders[0].id", Matchers.equalTo("oid0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.orders[0].name", Matchers.equalTo("order0")));

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users1.id", Matchers.equalTo("uid1")));
    }

    @Test
    public void resolveEntitySetArgumentTester() throws Exception {
        LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        params.add("users[1].id", "uid1");
        params.add("users[0].id", "uid0");
        params.add("users[0].username", "username0");
        params.add("users[0].name", "name0");
        params.add("users[0].birthDay", "2019-09-09");
        params.add("users[0].orders[0].id", "oid0");
        params.add("users[0].orders[0].name", "order0");
        params.add("test", "test");
        params.add("users1[0].id", "uid3");

        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/request_response_body/resolve_entity_set_argument");
        builder.contentType("application/x-www-form-urlencoded ");
        builder.params(params);

        ResultActions resultActions = this.mvc.perform(builder);

        resultActions.andExpect(MockMvcResultMatchers.status().isOk());
        resultActions.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8));
        //打印信息
        resultActions.andDo(MockMvcResultHandlers.print());
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.test", Matchers.equalTo("test")));

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].id", Matchers.equalTo("uid0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].name", Matchers.equalTo("name0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].username", Matchers.equalTo("username0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].birthDay", Matchers.equalTo("2019-09-09")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].orders[0].id", Matchers.equalTo("oid0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].orders[0].name", Matchers.equalTo("order0")));

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[1].id", Matchers.equalTo("uid1")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users1[0].id", Matchers.equalTo("uid3")));
    }

    @Test
    public void resolveEntityArrayArgumentTester() throws Exception {
        LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        params.add("users[1].id", "uid1");
        params.add("users[0].id", "uid0");
        params.add("users[0].username", "username0");
        params.add("users[0].name", "name0");
        params.add("users[0].birthDay", "2019-09-09");
        params.add("users[0].orders[0].id", "oid0");
        params.add("users[0].orders[0].name", "order0");
        params.add("test", "test");
        params.add("users1[0].id", "uid3");

        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/request_response_body/resolve_entity_array_argument");
        builder.contentType("application/x-www-form-urlencoded ");
        builder.params(params);

        ResultActions resultActions = this.mvc.perform(builder);

        resultActions.andExpect(MockMvcResultMatchers.status().isOk());
        resultActions.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8));
        //打印信息
        resultActions.andDo(MockMvcResultHandlers.print());
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.test", Matchers.equalTo("test")));

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].id", Matchers.equalTo("uid0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].name", Matchers.equalTo("name0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].username", Matchers.equalTo("username0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].birthDay", Matchers.equalTo("2019-09-09")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].orders[0].id", Matchers.equalTo("oid0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].orders[0].name", Matchers.equalTo("order0")));

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[1].id", Matchers.equalTo("uid1")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users1[0].id", Matchers.equalTo("uid3")));
    }

    @Test
    public void resolveEntityListArgumentTester() throws Exception {
        LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        params.add("users[1].id", "uid1");
        params.add("users[0].id", "uid0");
        params.add("users[0].username", "username0");
        params.add("users[0].name", "name0");
        params.add("users[0].birthDay", "2019-09-09");
        params.add("users[0].orders[0].id", "oid0");
        params.add("users[0].orders[0].name", "order0");
        params.add("test", "test");
        params.add("users1[0].id", "uid3");

        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/request_response_body/resolve_entity_list_argument");
        builder.contentType("application/x-www-form-urlencoded ");
        builder.params(params);

        ResultActions resultActions = this.mvc.perform(builder);

        resultActions.andExpect(MockMvcResultMatchers.status().isOk());
        resultActions.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8));
        //打印信息
        resultActions.andDo(MockMvcResultHandlers.print());
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.test", Matchers.equalTo("test")));

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].id", Matchers.equalTo("uid0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].name", Matchers.equalTo("name0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].username", Matchers.equalTo("username0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].birthDay", Matchers.equalTo("2019-09-09")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].orders[0].id", Matchers.equalTo("oid0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[0].orders[0].name", Matchers.equalTo("order0")));

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users[1].id", Matchers.equalTo("uid1")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users1[0].id", Matchers.equalTo("uid3")));
    }

    @Test
    public void resolveEntityMapArgumentTester() throws Exception {
        LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        params.add("users[1].id", "uid1");
        params.add("users[0].id", "uid0");
        params.add("users[0].username", "username0");
        params.add("users[0].name", "name0");
        params.add("users[0].birthDay", "2019-09-09");
        params.add("users[0].orders[0].id", "oid0");
        params.add("users[0].orders[0].name", "order0");
        params.add("test", "test");
        params.add("users1[0].id", "uid3");

        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/request_response_body/resolve_entity_map_argument");
        builder.contentType("application/x-www-form-urlencoded ");
        builder.params(params);

        ResultActions resultActions = this.mvc.perform(builder);

        resultActions.andExpect(MockMvcResultMatchers.status().isOk());
        resultActions.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8));
        //打印信息
        resultActions.andDo(MockMvcResultHandlers.print());
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.test", Matchers.equalTo("test")));

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.0.id", Matchers.equalTo("uid0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.0.name", Matchers.equalTo("name0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.0.username", Matchers.equalTo("username0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.0.birthDay", Matchers.equalTo("2019-09-09")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.0.orders[0].id", Matchers.equalTo("oid0")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.0.orders[0].name", Matchers.equalTo("order0")));

        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users.1.id", Matchers.equalTo("uid1")));
        resultActions.andExpect(MockMvcResultMatchers.jsonPath("$.data.users1.0.id", Matchers.equalTo("uid3")));
    }
}
